✨ Add fuse-two-qubit-unitary-runs pass#1865
Conversation
Add a `fuse-two-qubit-unitary-runs` MLIR pass that fuses compile-time two-qubit unitary windows and resynthesizes them to a native gateset via Weyl/KAK decomposition. Includes the pass definition, implementation, unit tests, and CMake wiring. Also add the `isEquivalentUpToGlobalPhase` matrix helper used by the new tests to compare unitaries up to a global phase. Assisted-by: Claude Opus 4.8 via Cursor Co-authored-by: Cursor <cursoragent@cursor.com>
…ry-runs` pass and remove outdated PR link
fuse-two-qubit-unitary-runs passfuse-two-qubit-unitary-runs pass
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
… metadata management
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds an MLIR QCO pass that fuses two-qubit unitary runs, resynthesizes them to a native gateset, and validates the result. Compiler, CLI, and Python APIs, reusable single-qubit fusion wiring, tests, and changelog entries are also added. ChangesTwo-Qubit Unitary Fusion Pass
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mlir/include/mlir/Dialect/QCO/Transforms/Passes.td`:
- Around line 88-89: The gate-set docs in Passes.td are advertising the
unsupported `p` alias even though `parseGateToken` only recognizes `rz`, so
update the `QCO` pass descriptions to match the parser by either adding `p`
handling in `parseGateToken` or removing `p` from the documented token list and
any related examples/comments. Make sure the wording around the gate tokens in
the pass definitions stays consistent with the actual accepted syntax.
In `@mlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseTwoQubitUnitaryRuns.cpp`:
- Around line 248-250: The comparison in the `FuseTwoQubitUnitaryRuns` scan is
unsafe because `uniqueUnitaryUser()` does not guarantee `nextOnA` and `nextOnB`
are in the same block, so `isBeforeInBlock` can trip MLIR preconditions when the
run spans blocks or regions. Update the logic around the `aSingle`/`bSingle`
check to first verify both successors are in the same block, and if not, stop
the scan before calling `isBeforeInBlock`; use the existing `nextOnA`,
`nextOnB`, and `sameOp` flow in `FuseTwoQubitUnitaryRuns.cpp` to place this
guard.
In `@mlir/unittests/Dialect/QCO/Transforms/NativeSynthesis/CMakeLists.txt`:
- Around line 12-26: The NativeSynthesis test target is missing the MemRef
dialect dependency even though the test registers memref::MemRefDialect in the
related test source. Update the target_link_libraries list for the test target
to include MLIRMemRefDialect alongside the existing MLIR dialect libraries,
matching the pattern used by other QCO test targets such as test_qc_ir.cpp and
test_qc_to_qco.cpp.
In
`@mlir/unittests/Dialect/QCO/Transforms/NativeSynthesis/test_fuse_two_qubit_unitary_runs.cpp`:
- Around line 388-390: The boundary comment in the test is stale and contradicts
the current pass behavior: in the scenario around the entangler and the
three-qubit gate, the wider gate should be described as stopping the run scan
and being left untouched, not “for the pass to reject.” Update the comment near
the affected test case in test_fuse_two_qubit_unitary_runs.cpp so it matches the
contract exercised by the surrounding test and the NativeSynthesis pass
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: dbd760f5-f291-4778-bbd7-825ed27db900
📒 Files selected for processing (11)
CHANGELOG.mdmlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Euler.hmlir/include/mlir/Dialect/QCO/Transforms/Decomposition/NativeGateset.hmlir/include/mlir/Dialect/QCO/Transforms/Passes.tdmlir/lib/Dialect/QCO/Transforms/Decomposition/NativeGateset.cppmlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseSingleQubitUnitaryRuns.cppmlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseTwoQubitUnitaryRuns.cppmlir/unittests/Dialect/QCO/Transforms/CMakeLists.txtmlir/unittests/Dialect/QCO/Transforms/Decomposition/test_weyl_decomposition.cppmlir/unittests/Dialect/QCO/Transforms/NativeSynthesis/CMakeLists.txtmlir/unittests/Dialect/QCO/Transforms/NativeSynthesis/test_fuse_two_qubit_unitary_runs.cpp
|
@coderabbitai review |
✅ Action performedReview finished.
|
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
…r the corresponding pass.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
mlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseTwoQubitUnitaryRuns.cpp (1)
349-354: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick winPrevent compiler crash by verifying the operation is a two-qubit gate.
LowerTwoQubitOpPatternmatches anyUnitaryOpInterface. If an off-gateset single-qubit gate (e.g., one with an unknown/dynamic matrix that couldn't be fused) or a >2-qubit gate reaches this pattern,spec.allowsOp(raw)will evaluate tofalse. The operation will then be passed toassignTwoQubitOpMatrix. Since it is not aCtrlOp,assignTwoQubitOpMatrixwill trigger its internal assertion (assert(unitary.isTwoQubit() ...)) and crash the compiler.Add a guard to ensure only two-qubit operations are processed by this lowering pattern.
🛡️ Proposed fix
LogicalResult matchAndRewrite(UnitaryOpInterface op, PatternRewriter& rewriter) const override { + if (!op.isTwoQubit()) { + return failure(); + } Operation* raw = op.getOperation(); if (!isWalkableUnitaryShell(raw) || spec.allowsOp(raw)) { return failure();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseTwoQubitUnitaryRuns.cpp` around lines 349 - 354, Update LowerTwoQubitOpPattern::matchAndRewrite to reject operations unless op represents exactly a two-qubit unitary before calling assignTwoQubitOpMatrix. Keep the existing isWalkableUnitaryShell and spec.allowsOp checks, and return failure for single-qubit or greater-than-two-qubit operations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@mlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseTwoQubitUnitaryRuns.cpp`:
- Around line 349-354: Update LowerTwoQubitOpPattern::matchAndRewrite to reject
operations unless op represents exactly a two-qubit unitary before calling
assignTwoQubitOpMatrix. Keep the existing isWalkableUnitaryShell and
spec.allowsOp checks, and return failure for single-qubit or
greater-than-two-qubit operations.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: bc6413a9-c136-4b15-b30a-b93f897dfc36
📒 Files selected for processing (13)
CHANGELOG.mdbindings/mlir/register_mlir.cppmlir/include/mlir/Compiler/Programs.hmlir/include/mlir/Dialect/QCO/Transforms/Passes.tdmlir/lib/Compiler/Programs.cppmlir/lib/Dialect/QCO/Transforms/Decomposition/NativeGateset.cppmlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseTwoQubitUnitaryRuns.cppmlir/lib/Support/Passes.cppmlir/tools/mqt-cc/mqt-cc.cppmlir/unittests/Compiler/test_compiler_pipeline.cppmlir/unittests/Dialect/QCO/Transforms/Decomposition/test_weyl_decomposition.cppmlir/unittests/Dialect/QCO/Transforms/NativeSynthesis/test_fuse_two_qubit_unitary_runs.cpppython/mqt/core/mlir.pyi
|
@coderabbitai review |
✅ Action performedReview finished.
|
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com> Assisted-by: Cursor Grok 4.5 via Cursor
Description
Add a
fuse-two-qubit-unitary-runsMLIR pass that fuses compile-time two-qubit unitary windows and resynthesizes them to a native gateset via Weyl/KAK decomposition.AI Assistance
Used
Composer 2.5via Cursor for parts of this change. I reviewed the fulldiff and take responsibility for everything in this PR.
Checklist
If PR contains AI-assisted content:
Assisted-by: [Model Name] via [Tool Name]footer.